package com.ayf.payment.game.api.excel.alipay;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.ayf.payment.game.api.dto.alipay.AliOrderStatus;
import com.ayf.payment.game.api.entity.MerchantAliBatchPayFile;
import com.ayf.payment.game.api.entity.MerchantAliBatchPayFileFailReason;
import com.ayf.payment.game.api.entity.MerchantAlipayOrder;
import com.ayf.payment.game.api.exception.ParameterException;
import com.ayf.payment.game.api.service.MerchantAlipayOrderService;
import com.ayf.payment.game.api.utils.BigDecimalUtil;
import com.ayf.payment.game.api.utils.DateUtils;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Description: excel数据导入
 * @Author: zh-liang
 * @Date : 2020-04-17 15:51
 */
public class UploadAliPayOrderListener extends AnalysisEventListener<UploadAliPayOrderData> {

    private static final int BATCH_COUNT = 500;

    private final List<MerchantAlipayOrder> successList = new ArrayList<>();
    private final List<MerchantAliBatchPayFileFailReason> failList = new ArrayList<>();
    private BigDecimal totalAmt = BigDecimal.ZERO;
    private int lineNum = 2;

    private final MerchantAlipayOrderService merchantAlipayOrderService;
    private final Integer merchantId;
    private final String traceId;
    private final String fileName;
    private final String batchPayFileId;
    private final String bathNo;

    /**
     * 每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param traceId
     * @param merchantId
     * @param fileName
     * @param merchantAlipayOrderService
     */
    public UploadAliPayOrderListener(String traceId, Integer merchantId, String fileName, MerchantAlipayOrderService merchantAlipayOrderService) {
        this.merchantAlipayOrderService = merchantAlipayOrderService;
        this.merchantId = merchantId;
        this.traceId = traceId;
        this.fileName = fileName;
        this.batchPayFileId = SnowFlakeUtils.getUniqueId();
        this.bathNo = "ZC".concat(DateUtils.dateToString(DateUtils.getNowDate(), "yyMMdd").concat(SnowFlakeUtils.getUniqueId()));
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param payOrderData
     * @param context
     */
    @Override
    public void invoke(UploadAliPayOrderData payOrderData, AnalysisContext context) {
        LogPortal.info("[{}]支付宝批量代付导入-解析到一条数据:[{}]", traceId, JSON.toJSONString(payOrderData));
        checkData(payOrderData);
        if (lineNum - 1 > BATCH_COUNT) {
            throw new ParameterException("支付宝批量代付导入失败，最大仅支持" + BATCH_COUNT + "条数据导入");
        }
        lineNum++;
    }

    /**
     * 所有数据解析完成了 才会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if (successList.size() == 0 && failList.size() == 0) {
            throw new ParameterException("Excel数据为空");
        }
        //保存上传文件信息
        MerchantAliBatchPayFile batchPayFile = new MerchantAliBatchPayFile();
        batchPayFile.setId(batchPayFileId);
        batchPayFile.setMerchantId(merchantId);
        batchPayFile.setBatchNo(bathNo);
        batchPayFile.setCreateTimeIndex(DateUtils.dateToInteger(new Date()));
        batchPayFile.setFileName(fileName);
        batchPayFile.setTotalAmt(totalAmt);
        batchPayFile.setTotalCount(lineNum - 2);
        if (CollUtil.isNotEmpty(failList)) {
            batchPayFile.setStatus(1);
        } else {
            batchPayFile.setStatus(2);
        }
        if (merchantAlipayOrderService.bathAddAliPayOrder(successList, failList, batchPayFile)) {
            LogPortal.info("[{}]支付宝批量代付导入-所有数据解析处理完成！", traceId);
        } else {
            LogPortal.info("[{}]支付宝批量代付导入-所有数据解析处理失败！", traceId);
        }
    }

    /**
     * 校检数据
     *
     * @return
     */
    private void checkData(UploadAliPayOrderData data) {
        boolean boo = true;
        if (StringUtils.isBlank(data.getAccountNo())) {
            MerchantAliBatchPayFileFailReason failReason = new MerchantAliBatchPayFileFailReason();
            failReason.setId(SnowFlakeUtils.getUniqueId());
            failReason.setBatchPayFileId(batchPayFileId);
            failReason.setFailPosition("第" + lineNum + "行");
            failReason.setFailDescription("收款账号不能为空");
            failList.add(failReason);
            boo = false;
        } else if (!Validator.isMobile(data.getAccountNo()) && !Validator.isEmail(data.getAccountNo())) {
            MerchantAliBatchPayFileFailReason failReason = new MerchantAliBatchPayFileFailReason();
            failReason.setId(SnowFlakeUtils.getUniqueId());
            failReason.setBatchPayFileId(batchPayFileId);
            failReason.setFailPosition("第" + lineNum + "行");
            failReason.setFailDescription("收款账号格式错误，只支持手机号或邮箱");
            failList.add(failReason);
            boo = false;
        }
        if (StringUtils.isBlank(data.getName())) {
            MerchantAliBatchPayFileFailReason failReason = new MerchantAliBatchPayFileFailReason();
            failReason.setId(SnowFlakeUtils.getUniqueId());
            failReason.setBatchPayFileId(batchPayFileId);
            failReason.setFailPosition("第" + lineNum + "行");
            failReason.setFailDescription("收款人姓名不能为空");
            failList.add(failReason);
            boo = false;
        } else if (!Validator.isChinese(data.getName())) {
            MerchantAliBatchPayFileFailReason failReason = new MerchantAliBatchPayFileFailReason();
            failReason.setId(SnowFlakeUtils.getUniqueId());
            failReason.setBatchPayFileId(batchPayFileId);
            failReason.setFailPosition("第" + lineNum + "行");
            failReason.setFailDescription("收款人姓名格式错误-只支持汉字");
            failList.add(failReason);
            boo = false;
        }
        if (data.getTransAmount() == null) {
            MerchantAliBatchPayFileFailReason failReason = new MerchantAliBatchPayFileFailReason();
            failReason.setId(SnowFlakeUtils.getUniqueId());
            failReason.setBatchPayFileId(batchPayFileId);
            failReason.setFailPosition("第" + lineNum + "行");
            failReason.setFailDescription("付款金额不能为空");
            failList.add(failReason);
            boo = false;
        } else if (data.getTransAmount().compareTo(BigDecimal.ONE) < 0) {
            MerchantAliBatchPayFileFailReason failReason = new MerchantAliBatchPayFileFailReason();
            failReason.setId(SnowFlakeUtils.getUniqueId());
            failReason.setBatchPayFileId(batchPayFileId);
            failReason.setFailPosition("第" + lineNum + "行");
            failReason.setFailDescription("付款金额最低1元");
            failList.add(failReason);
            boo = false;
        } else if (data.getTransAmount().compareTo(new BigDecimal("50000.00")) > 0) {
            MerchantAliBatchPayFileFailReason failReason = new MerchantAliBatchPayFileFailReason();
            failReason.setId(SnowFlakeUtils.getUniqueId());
            failReason.setBatchPayFileId(batchPayFileId);
            failReason.setFailPosition("第" + lineNum + "行");
            failReason.setFailDescription("付款金额最大5万元");
            failList.add(failReason);
            boo = false;
        } else {
            totalAmt = BigDecimalUtil.amtHalfUp(totalAmt.add(data.getTransAmount()));
        }
        if (boo) {
            MerchantAlipayOrder alipayOrder = new MerchantAlipayOrder();
            alipayOrder.setName(data.getName());
            alipayOrder.setAccountNo(data.getAccountNo());
            alipayOrder.setTransAmount(data.getTransAmount());
            alipayOrder.setRemark(data.getRemark());
            alipayOrder.setId(SnowFlakeUtils.getUniqueId());
            alipayOrder.setMerchantId(merchantId);
            alipayOrder.setMerchantOrderNo("ZD".concat(DateUtils.dateToString(DateUtils.getNowDate(), "yyMMdd").concat(SnowFlakeUtils.getUniqueId())));
            alipayOrder.setStatus(AliOrderStatus.CREAT.getCode());
            alipayOrder.setBathNo(bathNo);
            alipayOrder.setPayType(1);
            Date date = new Date();
            alipayOrder.setCreateTime(date);
            alipayOrder.setCreateDateIndex(DateUtils.dateToInteger(date));
            successList.add(alipayOrder);
        }
        LogPortal.info("[{}]支付宝批量代付导入-本次校检结果为[{}]", traceId, boo);
    }
}
